package org.apache.solr.util;

import java.io.*;
import java.nio.channels.FileChannel;

public class FileUtils {

    /**
     * Resolves a path relative a base directory.
     *
     * <p> This method does what "new File(base,path)" <b>Should</b> do, if it
     * wasn't completely lame: If path is absolute, then a File for that path is
     * returned; if it's not absolute, then a File is returned using "path" as a
     * child of "base") </p>
     */
    public static File resolvePath(File base, String path) {

        File r = new File(path);
        return r.isAbsolute() ? r : new File(base, path);
    }

    public static void copyFile(File src, File destination) throws IOException {

        try(
            FileChannel in = new FileInputStream(src).getChannel();
            FileChannel out = new FileOutputStream(destination).getChannel())
        {
            in.transferTo(0, in.size(), out);
        }
    }

    /**
     * Copied from Lucene's FSDirectory.fsync(String)
     *
     * @param fullFile the File to be synced to disk
     * @throws IOException if the file could not be synced
     */
    public static void sync(File fullFile) throws IOException {

        if (fullFile == null || !fullFile.exists()) {
            throw new FileNotFoundException("File does not exist " + fullFile);
        }

        boolean success = false;
        int retryCount = 0;
        IOException exc = null;
        while (!success && retryCount < 5) {
            retryCount++;
            try {
                try(RandomAccessFile file = new RandomAccessFile(fullFile, "rw")) {
                    file.getFD().sync();
                    success = true;
                }
            }
            catch (IOException ioe) {
                if (exc == null) {
                    exc = ioe;
                }
                try {
                    // Pause 5 msec
                    Thread.sleep(5);
                }
                catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                }
            }
        }
        if (!success) { // Throw original exception

            throw exc;
        }
    }
}
